/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package socof.wget;

import org.hyperic.sigar.Sigar;
import org.hyperic.sigar.SigarException;

/**
 *
 * @author Carlos Pinheiro
 */
public class ParsersBalancers extends Thread
{

    private static ParsersBalancers pc = new ParsersBalancers();
    private static final int WAIT_TIME = 1000;
    private Sigar sigar = new Sigar();
    
    private static final int PARSERS_LIMIT = 50;    
    private ResizeableSemaphore parsersSemaphore = new ResizeableSemaphore(0);
    private double maxCpuUsage;
    private int parsersLimit = PARSERS_LIMIT;
    
    private boolean paused = false;

    private ParsersBalancers()
    {
    }

    public static ParsersBalancers getInstance()
    {
        return pc;
    }

    @Override
    public void run()
    {
        ParsersLauncher pl = ParsersLauncher.getInstance();
        double cpuUsage;

        try
        {
            while (!isInterrupted() && !isPaused())
            {
                try
                {
                    maxCpuUsage = getMaxCpuUsage();
                    cpuUsage = sigar.getCpuPerc().getCombined();
                    if (cpuUsage < maxCpuUsage)
                    {
                        increaseParsers();
                    }
                    else
                    {
                        decreaseParsers();
                    }
                }
                catch (SigarException ex)
                {
                }

                Thread.sleep(WAIT_TIME);
            }
        }
        catch (InterruptedException ex)
        {
        }
    }
    
    public synchronized void setMaxCpuUsage (double maxCpuUsage)
    {
        this.maxCpuUsage = maxCpuUsage;
    }
    
    public synchronized double getMaxCpuUsage ()
    {
        return this.maxCpuUsage;
    }
    
    public synchronized void setParsersLimit (int parsersLimit)
    {
        this.parsersLimit = parsersLimit;
    }
    
    public void decreaseParsers()
    {
        if (getParsersSemaphore().getTotalPermits() > 1)
            getParsersSemaphore().removePermit();
    }
    
    public void increaseParsers()
    {
        if (getParsersSemaphore().getTotalPermits() < parsersLimit)
            getParsersSemaphore().addPermit();
    }
    
    public void removeAllParsers()
    {
        getParsersSemaphore().removeAllPermits();
    }
    
    public int getNumberOfParsers()
    {
        return getParsersSemaphore().getTotalPermits();
    }
    
    public int getNumberExecuting()
    {
        return getParsersSemaphore().getUsedPermits();
    }

    /**
     * @return the parsersSemaphore
     */
    public ResizeableSemaphore getParsersSemaphore()
    {
        return parsersSemaphore;
    }
    
    public synchronized void setPaused(boolean pause)
    {
        this.paused = pause;
        if (!this.paused)
            this.notify();
    }
    
    private synchronized boolean isPaused ()
    {
        if (this.paused)
        {
            try
            {
                this.removeAllParsers();
                this.wait();
            }
            catch (InterruptedException ex)
            {
                //Logger.getLogger(DownloadersController.class.getName()).log(Level.SEVERE, null, ex);
            }   
        }
        
        return this.paused;
    }
}
